#include "stdafx.h"
#include "ColorInterpolator.h"

#include <algorithm>

#ifdef _DEBUG
#define new DEBUG_NEW
#endif


CColorInterpolator::CColorInterpolator()
{
	UpdateColors();
}

CColorInterpolator::CColorInterpolator(COLORREF min, COLORREF max)
{
	InsertKey(SColorKey(min, 0.0f));
	InsertKey(SColorKey(max, 1.0f));
	SortKeys();
}

CColorInterpolator::~CColorInterpolator()
{
}

int CColorInterpolator::GetNumKeys() const
{
	return int(m_keys.size());
}

SColorKey* CColorInterpolator::GetKey(int i)
{
	if((i >= 0) &&
	   (i <= int(m_keys.size()) - 1))
	{
		return &m_keys[i];
	}
	else
		return NULL;
}

const SColorKey* CColorInterpolator::GetKey(int i) const
{
	if((i >= 0) &&
	   (i <= int(m_keys.size()) - 1))
	{
		return &m_keys[i];
	}
	else
		return NULL;
}

void CColorInterpolator::RemoveKey(int i)
{
	if((i >= 0) &&
	   (i <= int(m_keys.size()) - 1))
	{
		ColorKeys::iterator it = m_keys.begin();
		it += i;
		m_keys.erase(it);
	}
}

void CColorInterpolator::InsertKey(const SColorKey& pt)
{
	m_keys.push_back(pt);
}

void CColorInterpolator::SortKeys()
{
	std::sort(m_keys.begin(), m_keys.end());
	UpdateColors();
}

COLORREF CColorInterpolator::GetColor(double val) const
{
	if(val < 0.0f)
		val = 0.0f;
	if(val > 1.0f)
		val = 1.0f;
	int ind = int(val*float(COLOR_TABLE_SIZE - 1));
	return m_colors[ind];
}

COLORREF interpolate(COLORREF l, COLORREF r, double val)
{
	double dR = double(GetRValue(r) - GetRValue(l)),
		   dG = double(GetGValue(r) - GetGValue(l)),
		   dB = double(GetBValue(r) - GetBValue(l));
	BYTE R = GetRValue(l) + BYTE(val*dR),
		 G = GetGValue(l) + BYTE(val*dG),
		 B = GetBValue(l) + BYTE(val*dB);
	return RGB(R, G, B);
}

void CColorInterpolator::UpdateColors()
{
	if(int(m_keys.size()) < 2)
		return;

	for(int i = 0; i < COLOR_TABLE_SIZE; i++)
	{
		double val = double(i)/double(COLOR_TABLE_SIZE);

		int l = 0, r = int(m_keys.size()) - 1, c = 0;
		while(r - l > 1)
		{
			c = (l + r)/2;
			if(m_keys[c].m_pos > val)
				r = c;
			else
				l = c;
		}
		double delta = m_keys[r].m_pos - m_keys[l].m_pos;
		double valDelta = val - m_keys[l].m_pos;
		if(delta != 0.0f)
			valDelta = valDelta/delta;
		else
			valDelta = 0.0f;
		COLORREF lclr = m_keys[l].m_clr;
		COLORREF rclr = m_keys[r].m_clr;
		m_colors[i] = interpolate(lclr, rclr, valDelta);
	}
}